/**
 * @addtogroup mfc_serial_vir_bus
 * mfc_serial_vir_bus
 * @{
 */
/**
 * @file         mfc_serial_vir_bus.h
 * @brief        串行虚拟总线,屏蔽物理层串行总线，例如串口，网卡，spi，网络
 * @note    
 * @author       Akee
 * @date         2020-06-03
 * @version      1.0
 *
 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2020-06-03  <td>1.0                   <td>Akee            <td>创建初始版本
 * @copyright    杭州鸿泉物联网技术股份有限公司
 */
#ifndef _MFC_SERIAL_VIR_BUS_H_
#define _MFC_SERIAL_VIR_BUS_H_

#include "ofc_object.h"
#include "ofc_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * 总线的错误码
 */
enum TMfSerialVirBusErrorCodeTag
{
    kMfSerialVirBusErrorOk              = 0,    ///< 成功
    kMfSerialVirBusErrorError           = 1,    ///< 错误
    kMfSerialVirBusErrorTimeOut         = 2,    ///< 超时
    kMfSerialVirBusErrorNetNotReady     = 3,    ///< 总线未准备好,需要等到总线准备好后再次调用Connect函数
    kMfSerialVirBusErrorNotImp          = 4,    ///< 功能未实现
    kMfSerialVirBusErrorBusy            = 5,    ///< 总线正忙
    kMfSerialVirBusErrorConnectPending  = 6,    ///< 等待连接结果
    kMfSerialVirBusErrorUnknown         = 7,    ///< 不明原因的错误
    kMfSerialVirBusErrorConnected       = 8,    ///< 已经连接中
    kMfSerialVirBusErrorDisconnect      = 9,    ///< 未连接
};
typedef enum TMfSerialVirBusErrorCodeTag TMfSerialVirBusErrorCode;

/**
 * 
 */
typedef struct TMfSerialVirBusTag TMfSerialVirBus;





/**
 * 连接事件
 * @param sender: 调用者对象指针
 * @param host: ip
 * @param port: 端口
 * @return 参考TMfSerialVirBusErrorCode
 */
typedef TMfSerialVirBusErrorCode(*TMfSerialVirBusConnectEvent)(void *sender, const char *host, Int32 port);

/**
 * 发送事件
 * @param sender: 调用者对象指针
 * @param data: 数据缓冲区
 * @param size: 数据大小
 * @return 返回实际写入的数据数;如果网络未连接,返回-1
 */
typedef Int32(*TMfSerialVirBusSendEvent)(void *sender, const char *data, Int32 size);

/**
 * 接收事件
 * @param sender: 调用者对象指针
 * @param buf: 数据缓冲区
 * @param size: 数据大小
 * @return 返回实际写入的数据数;如果网络未连接,返回-1
 */
typedef Int32(*TMfSerialVirBusRecvEvent)(void *sender, char *buf, Int32 size);

/**
 * 通知事件
 * @param sender: 调用者对象指针
 * @return 参考TMfSerialVirBusErrorCode
 */
typedef Int32(*TMfSerialVirBusNotifyEvent)(void *sender);

/**
 * 通知事件
 * @param sender: 调用者对象指针
 * @return 参考TMfSerialVirBusErrorCode
 */
typedef Bool(*TMfSerialVirBusOnReadyEvent)(void *sender);

struct TMfSerialVirBusTag
{
PROTECTED
    TOfObject parent_;                ///< 基类

PROTECTED
    TOfVirtualMethod Destroy_;        ///< 析构事件
    TOfNotifyEvent OnDisconnect_;               ///< 断开事件
    TMfSerialVirBusConnectEvent OnConnect_;     ///< 连接事件
    TMfSerialVirBusSendEvent OnSend_;           ///< 发送事件
    TMfSerialVirBusRecvEvent OnRecv_;           ///< 接收事件
    TMfSerialVirBusNotifyEvent OnWriteAble_;    ///< 可写事件
    TMfSerialVirBusNotifyEvent OnReadAble_;     ///< 可读事件
    TMfSerialVirBusNotifyEvent OnGetConnectResult_; ///< 获取连接结果事件
    TMfSerialVirBusOnReadyEvent OnIsReady_;      ///< 总线准备事件
    TMfSerialVirBusNotifyEvent OnUnAckSize_;      ///< 未确认字节数事件

PROTECTED
        //Int32 send_size_;
    Bool connected_;                            ///< 是否已经连接
};

/**
 * 构造函数
 * @param self: 对象指针
 * @return 
 */
void TMfSerialVirBusCreate(TMfSerialVirBus *self);

/**
 * 连接服务器
 * @param self: 对象指针
 * @param host: 服务器名称或者IP地址
 * @param port: 端口
 * @return 连接成功返回kMfSerialVirBusErrorOk,其他返回错误码
 */
TMfSerialVirBusErrorCode TMfSerialVirBusConnect(TMfSerialVirBus *self, const char *host, Int32 port);

/**
 * 断开总线连接
 * @param self: 对象指针
 * @return
 */
void TMfSerialVirBusDisconnect(TMfSerialVirBus *self);

/**
 * 返回串行总线是否已经连接
 * @param self: 对象指针
 * @return 是否已经连接
 */
Bool TMfSerialVirBusConnected(TMfSerialVirBus *self);

/**
 * 总线是否准备好
 * @param self: 对象指针
 * @return True: 已经准备好; False: 未准备好
 */
Bool TMfSerialVirBusIsReady(TMfSerialVirBus *self);

/**
 * 发送数据
 * @note  调用这个函数前,最好调用TMfSerialVirBusWriteAble来检查是否可用发送
 * @param self: 对象指针
 * @param data: 数据缓冲区
 * @param size: 数据大小
 * @return 返回实际写入的数据数;如果网络未连接,返回-1
 */
Int32 TMfSerialVirBusSend(TMfSerialVirBus *self, const char *data, Int32 size);

/**
 * 读取数据
 * @note  1. 调用TMfSerialVirBusDisconnect()函数或者网络断开时,接收缓冲区的数据不会丢失,可用继续读取,直到读完.
 *        2. 调用TMfSerialVirBusConnect()函数时会清除所有接收缓冲区的数据
 *        3. 调用这个函数前,最好调用ReadAble来检查是否有数据可用读取,有多少数据可以读取
 * @param self: 对象指针
 * @param buf: 数据接收的缓冲区
 * @param size: 缓冲区大小
 * @return 返回实际读取到的数据数;如果网络未连接,返回-1
 */
Int32 TMfSerialVirBusRecv(TMfSerialVirBus *self, char *buf, Int32 size);

/**
 * 检查当前发送缓冲区是否可以写入.
 * @param self: 对象指针
 * @return 返回可以写入的数据数.如果是网络断开状态,返回-1,其他返回发送缓冲区的空闲缓冲区大小
 */
Int32 TMfSerialVirBusWriteAble(TMfSerialVirBus *self);

/**
 * 检查当前接收缓冲区中是否有数据可以读取.
 * @param self: 对象指针
 * @return 实际可以读取的数据数.如果缓冲区没有数据可以读取,则网络未断开返回0,网络已断开返回-1
 */
Int32 TMfSerialVirBusReadAble(TMfSerialVirBus *self);

/**
 * 获取连接结果
 * @param self: 对象指针
 * @return 参考TMfSerialVirBusErrorCode
 */
Int32 TMfSerialVirBusGetConnectResult(TMfSerialVirBus *self);

/**
 * 本次连接,缓冲区中的数据已经写入到总线的大小
 * @param self: 对象指针
 * @return 字节数
 */
//QWord TMfSerialVirBusSendSize(TMfSerialVirBus *self);

/**
 * 本次连接,模块已经发出去的数据,但服务器端尚未应答的数据数
 * @param self: 对象指针
 * @return 字节数，若事件未设置，则返回-1
 */
Int32 TMfSerialVirBusUnAckSize(TMfSerialVirBus *self);

#ifdef __cplusplus
} // extern "C" {
#endif

#endif

/**
 * @}
 */
